#include "threadPool.h"
#include <dirent.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/ioctl.h>
// 将传入字符串字母转换为小写字母
void str_to_lower(char *str);

int cdFunc(dirStack_t *dirstack, const char* destdir) {
    int i = 0, j = 0;
    char data[128];
    if (destdir[0] == '/') {
        cleanDirStack(dirstack);
        i = 1;
    } else if (destdir[0] == '\0') {
        cleanDirStack(dirstack);
    } else if (destdir[0] == '~') {
        if (destdir[1] == '/') {
            cleanDirStack(dirstack);
            i = 2;
        } else if (destdir[1] == '\0') {
            cleanDirStack(dirstack);
            i = 1;
        }
    }
    while (destdir[i] != '/' && destdir[i] != '\0') {
        memset(data, 0, sizeof(data));
        data[0] = '/';
        j = 1;
        while (destdir[i] != '/' && destdir[i] != '\0') {
            data[j] = destdir[i];
            ++i;
            ++j;
        }
        if (strcmp(data, "/.") == 0) {
        } else if (strcmp(data, "/..") == 0) {
            popDirStack(dirstack);
        } else {
            pushDirStack(dirstack, data);
        }
        if (destdir[i] == '/') {
            ++i;
        }
    }
    return 0;
}

int pwdFunc(dirStack_t *dirstack, char *pwd_result) {
    char pwd[4096] = {0};
    int offset = 0;
    if (dirstack->size == 0) {
        pwd[0] = '/';
        offset = 1;
    }
    dirNode_t *cur = dirstack->bottom->pnext;
    while (cur != NULL) {
        offset += snprintf(pwd + offset, sizeof(pwd) - offset, "%s", cur->data);
        cur = cur->pnext;
    }
    snprintf(pwd_result, sizeof(pwd), "%s", pwd);
    printf("pwd: \"%s\"\n", pwd);
    return 0;
}

int mkdirFunc(dirStack_t *dirstack, const char *pathname) {
    char temp[4096] = {0};
    snprintf(temp, sizeof(temp), "%s", pathname);
    char *token, *saveptr;
    token = strtok_r(temp, " ", &saveptr);
    while (token != NULL) {
        char mkdirpath[4096] = {0};
        getAbsDir(dirstack, token, mkdirpath);
        if (-1 == mkdir(mkdirpath, 0755)) {  // 失败返回-1
            return -1;
        }
        token = strtok_r(NULL, " ", &saveptr);
    }
    return 0;  // 成功返回0
}

int rmdirFunc(dirStack_t *dirstack, const char *pathname, char* error_msg) {
    char temp[4096] = {0};
    bool fail = false;
    char fail_msg[4096] = {0};
    int offset = 0;
    snprintf(temp, sizeof(temp), "%s", pathname);
    char *token, *saveptr;
    token = strtok_r(temp, " ", &saveptr);
    while (token != NULL) {
        char rmdirpath[4096] = {0};
        getAbsDir(dirstack, token, rmdirpath);
        if (-1 == rmdir(rmdirpath)) {
            int save_errno = errno;
            offset += snprintf(fail_msg + offset, sizeof(fail_msg) - offset,
                               "%s like \"%s\"\n", strerror(save_errno), token);
            fail = true;
        }
        token = strtok_r(NULL, " ", &saveptr);
    }
    if (fail) {
        snprintf(error_msg, sizeof(fail_msg), "%s", fail_msg);
    }
    return fail ? 1 : 0;  // 失败返回1, 成功返回0
}

// lsFunc
// 最大结果缓冲区大小
#define MAX_RESULT_SIZE 8192
// 最大列数
#define MAX_COLS 8

// 解析选项标志位
typedef struct {
    int all;        // -a 显示隐藏文件
    int list;       // -l 显示详细信息
} LsOptions;

// 文件条目结构
typedef struct {
    char name[256]; // 文件名
    struct stat stat_buf; // 文件属性
} FileEntry;

// 格式化文件权限字符串
void get_permission_string(mode_t mode, char *perm_str) {
    perm_str[0] = (S_ISDIR(mode))  ? 'd' :
        (S_ISLNK(mode))  ? 'l' :
        (S_ISFIFO(mode)) ? 'p' :
        (S_ISSOCK(mode)) ? 's' :
        (S_ISCHR(mode))  ? 'c' :
        (S_ISBLK(mode))  ? 'b' : '-';

    perm_str[1] = (mode & S_IRUSR) ? 'r' : '-';
    perm_str[2] = (mode & S_IWUSR) ? 'w' : '-';
    perm_str[3] = (mode & S_IXUSR) ? 'x' : '-';
    perm_str[4] = (mode & S_IRGRP) ? 'r' : '-';
    perm_str[5] = (mode & S_IWGRP) ? 'w' : '-';
    perm_str[6] = (mode & S_IXGRP) ? 'x' : '-';
    perm_str[7] = (mode & S_IROTH) ? 'r' : '-';
    perm_str[8] = (mode & S_IWOTH) ? 'w' : '-';
    perm_str[9] = (mode & S_IXOTH) ? 'x' : '-';
    perm_str[10] = '\0';
}

// 比较函数ïM`>/[M`>/[M`>/¼按文件名排序（字典序）
int compare_name(const void *a, const void *b) {
    const FileEntry *fa = (const FileEntry *)a;
    const FileEntry *fb = (const FileEntry *)b;
    return strcmp(fa->name, fb->name);
}

// 获取终端宽度
int get_terminal_width() {
    struct winsize w;
    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
        return w.ws_col;
    }
    return 80; // 默认宽度
}

// 实现 lsFunc                                                                                   
//int lsFunc(char *buf, char *result_buf) {
//    LsOptions options = {0, 0}; // 默认选项
//    /* char *path = "/home/hbin/code/linux/day11_work";           // 默认当前目录 */
//    printf("buf = %s\n", buf);
//    char *path = buf; // 默认当前目录
//    printf("path = %s\n", path);
//    char *token;
//    char *saveptr;
//    char temp_buf[MAX_RESULT_SIZE] = {0}; // 临时存储结果
//    int temp_len = 0;                     // 临时缓冲区长度
//
//    // 解析输入参数
//    token = strtok_r(buf, " ", &saveptr);
//    while (token != NULL) {
//        if (token[0] == '-') { // 处理选项
//            for (int i = 1; token[i] != '\0'; i++) {
//                if (token[i] == 'a') options.all = 1;
//                if (token[i] == 'l') options.list = 1;
//            }
//        } else { // 处理路径
//            path = token;
//        }
//        token = strtok_r(NULL, " ", &saveptr);
//    }
int lsFunc(dirStack_t *dirStack, char *buf, char *result_buf) {
    LsOptions options = {0, 0}; // 默认选项
    char path[4096] = {0};      // 默认当前目录
    concatDirStack(dirStack, path);
    char *token;
    char *saveptr;
    char temp_buf[MAX_RESULT_SIZE] = {0}; // 临时存储结果
    int temp_len = 0;                     // 临时缓冲区长度

    // 解析输入参数
    token = strtok_r(buf, " ", &saveptr);
    while (token != NULL) {
        if (token[0] == '-') { // 处理选项
            for (int i = 1; token[i] != '\0'; i++) {
                if (token[i] == 'a') options.all = 1;
                if (token[i] == 'l') options.list = 1;
            }
        } else { // 处理路径
            snprintf(path, sizeof(path), "%s", token);         
        }                                     
        token = strtok_r(NULL, " ", &saveptr);
    }                                         

    // 打开çM`>/[M`>/[M`>/®录
    DIR *dir = opendir(path);
    if (!dir) {
        snprintf(result_buf, MAX_RESULT_SIZE, "Error: Cannot open directory '%s'", path);
        return -1;
    }

    // 收集所有文件条目
    FileEntry *entries = NULL;
    size_t count = 0;
    size_t capacity = 32; // 初始容量
    entries = (FileEntry *)malloc(capacity * sizeof(FileEntry));
    if (!entries) {
        closedir(dir);
        strcpy(result_buf, "Error: Memory allocation failed");
        return -1;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        // 跳过隐藏文件（除非 -a 选项）
        if (!options.all && entry->d_name[0] == '.') continue;

        // 检查是否需要扩展数组
        if (count >= capacity) {
            capacity *= 2;
            FileEntry *new_entries = (FileEntry *)realloc(entries, capacity * sizeof(FileEntry));
            if (!new_entries) {
                free(entries);
                closedir(dir);
                strcpy(result_buf, "Error: Memory a[M`>/[M`>/llocation failed");
                return -1;
            }
            entries = new_entries;
        }

        // 存储文件名
        strncpy(entries[count].name, entry->d_name, sizeof(entries[count].name) - 1);
        entries[count].name[sizeof(entries[count].name) - 1] = '\0';
        count++;
    }
    closedir(dir);

    // 按字典序排序
    // 按字典序排序                                                                
    qsort(entries, count, sizeof(FileEntry), compare_name);

    // 如果需要详细列表，获取文件属性
    if (options.list) {
        for (size_t i = 0; i < count; i++) {
            char full_path[8192];
            snprintf(full_path, sizeof(full_path), "%s/%s", path, entries[i].name);
            lstat(full_path, &entries[i].stat_buf); // 忽略错误，使用默认属性
        }
    }

    // 生成输出
    if (options.list) { // 详细模式
        for (size_t i = 0; i < count; i++) {
            // 格式化权限
            char perm_str[11];
            get_permission_string(entries[i].stat_buf.st_mode, perm_str);

            // 获取用户名和组名
            struct passwd *pwd = getpwuid(entries[i].stat_buf.st_uid);
            struct group *grp = getgrgid(entries[i].stat_buf.st_gid);
            const char *user = pwd ? pwd->pw_name : "unknown";
            const char *group = grp ? grp->gr_name : "unknown";

            // 格式化时间
            char time_str[32];
            struct tm *tm_info = localtime(&entries[i].stat_buf.st_mtime);
            strftime(time_str, sizeof(time_str), "%b %d %H:%M", tm_info);

            // 格式化输出行
            char line_buf[512];
            snprintf(line_buf, sizeof(line_buf), "%s %2lu %-8s %-8s %8ld %s %s\n",
                     perm_str,
                     (unsigned long)entries[i].stat_buf.st_nlink,
                     user,
                     group,
                     (long)entries[i].stat_buf.st_size,
                     time_str,
                     entries[i].name);

            // 追加到结果
            size_t line_len = strlen(line_buf);
            if (temp_len + line_len < MAX_RESULT_SIZE - 1) {
                strcat(temp_buf, line_buf);
                temp_len += line_len;
            } else {
                break; // 防止缓冲区溢出
            }
        }
    } else { // 简单模式（多列对齐输出）
             // 1. 计算最长文件名长度
        size_t max_name_len = 0;
        for (size_t i = 0; i < count; i++) {
            size_t name_len = strlen(entries[i].name);
            if (name_len > max_name_len) max_name_len = name_len;
        }

        // 2. 计算列宽（文件名长度 + 2个空格）
        size_t col_width = max_name_len + 2;
        if (col_width < 8) col_width = 8; // 最小列宽

        // 3. 获取终端宽度（用于计算列数）
        int term_width = get_terminal_width();
        if (term_width < 20) term_width = 20; // 最小宽度

        // 4. 计算列数（基于终端宽度）
        size_t cols = term_width / col_width;
        if (cols < 1) cols = 1;
        if (cols > MAX_COLS) cols = MAX_COLS;

        // 5. 计算行数
        size_t rows = (count + cols - 1) / cols; // 向上取整

        // 6. 按列输出
        for (size_t row = 0; row < rows; row++) {
            for (size_t col = 0; col < cols; col++) {
                size_t index = row + col * rows;
                if (index >= count) continue;

                // 格式化文件名（固定宽度）
                char formatted[256];
                snprintf(formatted, sizeof(formatted), "%-*s", (int)col_width, entries[index].name);

                // 追加到结果
                size_t formatted_len = strlen(formatted);
                if (temp_len + formatted_len < MAX_RESULT_SIZE - 1) {
                    strcat(temp_buf, formatted);
                    temp_len += formatted_len;
                } else {
                    break; // 防止缓冲区溢出
                }
            }
            // 每行结束换行
            if (temp_len < MAX_RESULT_SIZE - 1) {
                strcat(temp_buf, "\n");
                temp_len++;
            } else {
                break;
            }
        }
    }

    // 复制结果到输出缓冲区
    strncpy(result_buf, temp_buf, MAX_RESULT_SIZE);
    result_buf[MAX_RESULT_SIZE - 1] = '\0'; // 确保终止符

    // 释放内存
    free(entries);
    return 0;
}
